/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.editor.ext; import java.io.Serializable; import java.io.IOException; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Comparator; import java.util.Iterator; /** * Java completion resolver that operates over two files. * One is skeleton file and it's read at once during * the build() methods. The other file is class body * file and it's read lazily as necessary. * * File structures: * Skeleton file: * class skeletons: * String: class name * String: package name * int: body seek offset * int: body len * * Body file: * class bodies: * int: modifiers * String: super class name * String: super class package name * int: field count * field count * field body * field body: * !!! dodelat * * * * @author Miloslav Metelka * @version 1.00 */ public class JCFileProvider extends JCompletion.AbstractProvider { static final int VERSION = 1; static final int OPCODE_ADD = 1; // adding new class public static final String SKEL_FILE_EXT = ".jcs"; // NOI18N public static final String BODY_FILE_EXT = ".jcb"; // NOI18N /** Global cache saving the string creations */ private static final StringCache strCache = new StringCache(200, 5003); static { // pre-cache standard strings strCache.putSurviveString(""); // NOI18N Iterator i = JCompletion.getPrimitiveClassIterator(); while (i.hasNext()) { strCache.putSurviveString(((JCClass)i.next()).getName()); } } FileStorage skels; FileStorage bodies; HashMap classes; int fileVersion; public JCFileProvider(String fileNamePrefix) { this(fileNamePrefix + SKEL_FILE_EXT, fileNamePrefix + BODY_FILE_EXT); } public JCFileProvider(String fileNameSkels, String fileNameBodies) { skels = new FileStorage(fileNameSkels, strCache); bodies = new FileStorage(fileNameBodies, strCache); } public void reset() { try { skels.resetFile(); bodies.resetFile(); // write version skels.open(true); skels.putInteger(VERSION); skels.close(); } catch (IOException e) { throw new Error("JCFileProvider: IOException thrown during Java Completion file provider reset.\n" + e); // NOI18N } } protected boolean appendClass(JCClass c) { try { skels.putInteger(OPCODE_ADD); writeClass(c); skels.write(); bodies.write(); } catch (IOException e) { e.printStackTrace(); return false; } return true; } public boolean append(JCClassProvider cp) { try { if (skels.getFileLength() <= 0) { // reset if necessary reset(); } skels.open(true); bodies.open(true); if (!super.append(cp)) { return false; } } catch (IOException e) { e.printStackTrace(); return false; } catch (Throwable t) { t.printStackTrace(); return false; } finally { boolean ok = true; try { skels.close(); } catch (IOException e) { e.printStackTrace(); ok = false; } try { bodies.close(); } catch (IOException e) { e.printStackTrace(); ok = false; } return ok; } } public Iterator getClasses() { int skelsFileLen; try { skels.open(false); skels.seek(0); skelsFileLen = skels.getFileLength(); if (skelsFileLen < 4) { // file exists but was not reset reset(); return new ArrayList().iterator(); // return empty iterator } skels.read(skelsFileLen); } catch (IOException e) { throw new Error("JCFileProvider: Java Completion cannot read class skeletons\n" + e); // NOI18N } finally { try { skels.close(); } catch (IOException e) { e.printStackTrace(); } } fileVersion = skels.getInteger(); ArrayList clsList = new ArrayList(); while (skels.getOffset() < skelsFileLen) { // till the last class int opcode = skels.getInteger(); if (opcode == OPCODE_ADD) { Cls cls = new Cls(); clsList.add(cls); } else { break; // Unsupported operation code } } skels.resetBytes(); // GC possibly large skels bytes array return clsList.iterator(); } void writeClass(JCClass c) throws IOException { // write body bodies.putInteger(c.getTagOffset()); writeClassName(c.getSuperclass(), bodies); // Write implemented interfaces JCClass[] interfaces = c.getInterfaces(); bodies.putInteger(interfaces.length); for (int i = 0; i < interfaces.length; i++) { writeClassName(interfaces[i], bodies); } // Write declared fields JCField[] fields = c.getFields(); bodies.putInteger(fields.length); for (int i = 0; i < fields.length; i++) { writeField(fields[i]); } // Write constructors JCConstructor[] constructors = c.getConstructors(); bodies.putInteger(constructors.length); for (int i = 0; i < constructors.length; i++) { writeConstructor(constructors[i]); } // Write methods JCMethod[] methods = c.getMethods(); bodies.putInteger(methods.length); for (int i = 0; i < methods.length; i++) { writeMethod(methods[i]); } // write skeleton writeClassName(c, skels); int modifiers = c.getModifiers(); if (c.isInterface()) { modifiers |= JCompletion.INTERFACE_BIT; } skels.putInteger(modifiers); skels.putInteger(bodies.getFilePointer()); skels.putInteger(bodies.getOffset()); } void writeType(JCType t) { writeClassName(t.getClazz(), bodies); bodies.putInteger(t.getArrayDepth()); } void writeParameter(JCParameter p) { bodies.putString(p.getName()); writeType(p.getType()); } void writeField(JCField f) { bodies.putString(f.getName()); writeType(f.getType()); bodies.putInteger(f.getTagOffset()); bodies.putInteger(f.getModifiers()); } void writeConstructor(JCConstructor c) { bodies.putInteger(c.getTagOffset()); bodies.putInteger(c.getModifiers()); JCParameter[] parameters = c.getParameters(); bodies.putInteger(parameters.length); for (int i = 0; i < parameters.length; i++) { writeParameter(parameters[i]); } JCClass[] exceptions = c.getExceptions(); bodies.putInteger(exceptions.length); for (int i = 0; i < exceptions.length; i++) { writeClassName(exceptions[i], bodies); } } void writeMethod(JCMethod m) { writeConstructor(m); bodies.putString(m.getName()); writeType(m.getReturnType()); } /** Write name and package of the given class */ void writeClassName(JCClass c, FileStorage fs) { fs.putString(c.getFullName()); fs.putInteger(c.getPackageName().length()); } private JCClass getSimpleClass(String fullName, int packageNameLen) { JCClass c = null; if (packageNameLen == 0) { c = JCompletion.getPrimitiveClass(fullName); } if (c == null) { String fullNameIntern = fullName.intern(); if (fullName != fullNameIntern) { // update cache with interned string strCache.putSurviveString(fullNameIntern); } c = JCompletion.getSimpleClass(fullNameIntern, packageNameLen); } return c; } JCClass readSimpleClass(FileStorage fs) { String fullName = fs.getString(); int packageNameLen = fs.getInteger(); return getSimpleClass(fullName, packageNameLen); } final class Cls extends JCompletion.AbstractClass { /** Seek position in the file of the class body */ int bodySeekPointer; /** Length of the class body in the file */ int bodyLen; public Cls() { JCClass c = readSimpleClass(skels); fullName = c.getFullName(); name = c.getName(); packageName = c.getPackageName(); modifiers = skels.getInteger(); bodySeekPointer = skels.getInteger(); bodyLen = skels.getInteger(); } /** Init internal representation */ protected void init() { body = new Body(); // set the right seek position and read try { bodies.open(false); bodies.seek(bodySeekPointer); bodies.read(bodyLen); bodies.close(); } catch (IOException e) { throw new Error("JCFileProvider: Java Completion cannot read class body of class " + this); // NOI18N } body.tagOffset = bodies.getInteger(); body.superClass = readSimpleClass(bodies); int cnt = bodies.getInteger(); body.interfaces = (cnt > 0) ? new JCClass[cnt] : JCompletion.EMPTY_CLASSES; for (int i = 0; i < cnt; i++) { body.interfaces[i] = readSimpleClass(bodies); } cnt = bodies.getInteger(); body.fields = (cnt > 0) ? new JCField[cnt] : JCompletion.EMPTY_FIELDS; for (int i = 0; i < cnt; i++) { body.fields[i] = new Fld(this); } cnt = bodies.getInteger(); body.constructors = (cnt > 0) ? new JCConstructor[cnt] : JCompletion.EMPTY_CONSTRUCTORS; for (int i = 0; i < cnt; i++) { body.constructors[i] = new Ctr(this); } cnt = bodies.getInteger(); body.methods = (cnt > 0) ? new JCMethod[cnt] : JCompletion.EMPTY_METHODS; for (int i = 0; i < cnt; i++) { body.methods[i] = new Mtd(this); } try { bodies.close(); } catch (IOException e) { e.printStackTrace(); } } } final class Typ extends JCompletion.BaseType { Typ() { clazz = readSimpleClass(bodies); arrayDepth = bodies.getInteger(); } } /** Description of the declared field */ final class Fld extends JCompletion.BaseField { Fld(JCClass clazz) { this.clazz = clazz; name = bodies.getString(); type = new Typ(); tagOffset = bodies.getInteger(); modifiers = bodies.getInteger(); } } private void readBC(JCompletion.BaseConstructor bc) { bc.tagOffset = bodies.getInteger(); bc.modifiers = bodies.getInteger(); int cnt = bodies.getInteger(); bc.parameters = (cnt > 0) ? new JCParameter[cnt] : JCompletion.EMPTY_PARAMETERS; for (int i = 0; i < cnt; i++) { bc.parameters[i] = new Prm(); } cnt = bodies.getInteger(); bc.exceptions = (cnt > 0) ? new JCClass[cnt] : JCompletion.EMPTY_CLASSES; for (int i = 0; i < cnt; i++) { bc.exceptions[i] = readSimpleClass(bodies); } } /** Read constructor */ final class Ctr extends JCompletion.BaseConstructor { Ctr(JCClass clazz) { this.clazz = clazz; readBC(this); } } /** Read method */ final class Mtd extends JCompletion.BaseMethod { Mtd(JCClass clazz) { this.clazz = clazz; readBC(this); name = bodies.getString(); returnType = new Typ(); } } /** Description of the method parameter */ public class Prm extends JCompletion.BaseParameter { Prm() { name = bodies.getString(); type = new Typ(); } } public String toString() { return "strCache=" + strCache; // NOI18N } } /* * Log * 10 Gandalf 1.9 1/13/00 Miloslav Metelka Localization * 9 Gandalf 1.8 11/8/99 Miloslav Metelka * 8 Gandalf 1.7 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 7 Gandalf 1.6 10/10/99 Miloslav Metelka * 6 Gandalf 1.5 9/15/99 Miloslav Metelka * 5 Gandalf 1.4 8/18/99 Miloslav Metelka * 4 Gandalf 1.3 7/30/99 Miloslav Metelka * 3 Gandalf 1.2 7/22/99 Miloslav Metelka * 2 Gandalf 1.1 7/21/99 Miloslav Metelka * 1 Gandalf 1.0 7/20/99 Miloslav Metelka * $ */